This invention relates in general to digital processing and more specifically to prevention of an attack on a network device by monitoring and restricting a buffer allocation within the device.
Although large digital networks such as the Internet achieve much of their popularity and power by allowing relatively unrestricted access, such open access can cause problems when unknown user's, processes or devices (i.e., an attacker) try to perform unwanted acts such as reading protected information, modifying data or executable information, or causing a malfunction or other unwanted behavior of the network or a network process, processor or device on the network (i.e., a “node”). An intentional cause of unwanted behavior of the network or a node is referred to as an “attack” by a malicious attacker. Other unwanted acts may be accidental or unintended and can arise without human intervention or direction but can do the same type of damage and behave in a similar manner to an intentional attack. In general, an “attack” for purposes of this specification includes any type of malfunction or unwanted behavior of a network or node.
There are many different types of network attacks and threats. For example, unauthorized access, exploitation of known weaknesses, spoofing, eavesdropping and denial of service are some types of attacks or threats that can be used alone or in combination with other so-called hacking techniques. Certain types of attacks such as denial of service work by sending information to a network device that causes the network device to malfunction or fail. For example, a large attachment to an email message was an early way to bring down the first primitive email servers. Although safeguards have improved, there are still weaknesses in network devices that allow certain types of attacks.
A more modern attack is to send out-of-order packets to a routing device such as a router, switch, server or other routing processor. If the device is programmed to retain out of order packets in an attempt to reorder or reassemble the packets before forwarding the message, the occurrence of a large number of out-of-order packets can mean the device must keep storing thousands or more packets and may finally run out of memory space. Such a condition could cause an error, such as a lost message, or failure of the device as where the device's processor does not have sufficient memory with which to operate. This type of attack is referred to as a “state holding” attack since it arises due to the device attempting to maintain the proper state of out of order packets or segments.
Some devices need to deal with many different message streams or flows at the same time. For example, security devices such as firewalls and Intrusion Detection Systems (IDS) require reassembly of Transfer Control Protocol (TCP) segments before application layer (L7) inspection can be done. These devices usually need to buffer out-of-order segments until a contiguous set of ordered segments is available for processing.
In these devices, buffer space may be dynamically allocated to a flow based on the detection or prediction of that flow's needs. If one flow is experiencing a large amount of lost or unordered packets then increasing amounts of buffer space might be diverted to the problematic flow. However, this means that the performance of packet reordering in the other flows may be hindered due to lack of buffer space. In a case where a flow has become problematic due to a prolonged attack, the device may be severely impaired in its ability to handle other flows' traffic in an efficient, or even marginally functional, way.
Some approaches to solving the buffer allocation problem include simply placing a hard limit to the amount of buffer space that a flow can use. However, this often results in sub-optimal buffer utilization. Another approach can be found in Stream4 for Snort where older or “stale” flows are deleted if memory usage is high among active flows. Flows can also be picked at random for deletion. This approach is susceptible to a state holding type of attack.
Linux (2.4) uses an approach to maintain system-wide thresholds to limit buffer usage of a flow. For applications that have not explicitly set the Transmission Control Protocol (TCP) send and receive buffer sizes, the kernel attempts to grow the window sizes to match the available buffers size (up to the receiver's default window). If there is high demand for kernel/network memory, buffer size may be limited.
A flow can get any amount of memory provided the system buffer usage is below a low water mark. If the system memory usage grows beyond this threshold, the remaining buffers for TCP get equally divided among active flows. By reserving memory for flows that may never need it, this mechanism provides an absolute fairness at the expense of sub-optimal buffer utilization.
A paper entitled “Automatic TCP Buffer Tuning” by Jerey Semke et. al., Pittsburgh Supercomputing Center, describes a max-min fair share type of algorithm. In this approach, every connection gets up to 1/Nth of the unallocated pool, taking no more than what it needs. If a connection needs less that its 1/Nth portion, the remainder of the portion is left in the pool. After giving each connection a slice, the remaining unallocated pool is divided up among the unsatisfied connections, continuing in this manner until either the pool is empty or all connections are satisfied.
However, these approaches are suited for environments where all sessions are known to be trusted and do not provide protection in the case of a deliberate attack. Also, to ensure fair sharing the computation to calculate a flow's fair share must be performed relatively often. This can be a significant system overhead. The auto tuning approach of Linux reserves memory for flows that may never need it and thus is not useful for systems with large number of concurrent flows.
Although some approaches might be improved with memory recovery techniques, such as garbage collection, these recovery techniques can also be compute-intensive. Also, the garbage collection based approach dumps segments based on the instantaneous buffer usage of a flow and hence causes a bursty behavior. Since the Round Trip Time (RTT) of flows differs widely, the expected time of a segment in the queue also varies. A flow having large number of unordered segments should not be penalized provided the average arrival and departure rate of segments over a window of time is almost the same.